package com.ascent.server;

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.io.*;
import com.ascent.bean.Product;

/**
 * 产品数据读取的实现类
 * @author ascent
 * @version 1.0
 */
public class ProductDataAccessor extends DataAccessor {

	// ////////////////////////////////////////////////////
	//
	// 产品文件格式如下
	// 产品名称,化学文摘登记号,结构图,公式,价格,数量,类别
	// ----------------------------------------------------
	//
	// ////////////////////////////////////////////////////
	/**
	 * 商品信息数据文件名
	 */
	protected static final String PRODUCT_FILE_NAME = "database/product.db";

	/**
	 * 数据记录的分割符
	 */
	protected static final String RECORD_SEPARATOR = "----------";

	/**
	 * 默认构造方法
	 */
	public ProductDataAccessor() {
		load();
	}

	/**
	 * 读取数据的方法
	 */
	@Override
	public void load() {

		dataTable = new HashMap<String,ArrayList<Product>>();

		ArrayList<Product> productArrayList = null;
		StringTokenizer st = null;

		Product productObject = null;
		String line = "";

		String productName, cas, structure, formula, price, realstock, category;


		try {
			log("读取文件: " + PRODUCT_FILE_NAME + "...");
			BufferedReader inputFromFile1 = new BufferedReader(new FileReader(PRODUCT_FILE_NAME));

			while ((line = inputFromFile1.readLine()) != null) {

				st = new StringTokenizer(line, ",");

				productName = st.nextToken().trim();
				cas = st.nextToken().trim();
				structure = st.nextToken().trim();
				formula = st.nextToken().trim();
				price = st.nextToken().trim();
				realstock = st.nextToken().trim();
				category = st.nextToken().trim();

				productObject = getProductObject(productName, cas, structure,formula, price, realstock, category);

				if (dataTable.containsKey(category)) {
					productArrayList = dataTable.get(category);
				} else {
					productArrayList = new ArrayList<Product>();
					dataTable.put(category, productArrayList);
				}
				productArrayList.add(productObject);
			}

			inputFromFile1.close();
			log("文件读取结束!");


		} catch (FileNotFoundException exc) {
			log("没有找到文件: " + PRODUCT_FILE_NAME +".");
			log(exc);
		} catch (IOException exc) {
			log("读取文件发生异常: " + PRODUCT_FILE_NAME+ ".");
			log(exc);
		}
	}

	/**
	 * 新增产品数据
	 * @param product
	 */
	public void saveProduct(Product product){
		log("读取文件: " + PRODUCT_FILE_NAME + "...");
		try {
			String productInfo = product.getProductname()+","+product.getCas()+","+product.getStructure()+","+ product.getFormula()+","+ product.getPrice()+","+ product.getRealstock()+","+ product.getCategory();
			RandomAccessFile fos = new RandomAccessFile(PRODUCT_FILE_NAME,"rws");
			fos.seek(fos.length());
			fos.write((productInfo + "\n").getBytes());
			fos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 增加新的产品
	 * @param theProduct 被添加到购物车的商品
	 */
	public void addProduct(Product theProduct) {
		String category = theProduct.getCategory();
		log("添加新的产品:  " + theProduct);
		ArrayList<Product> productList = dataTable.get(category);
		productList.add(theProduct);
		recentProductList.add(theProduct);
		log("完成添加新的产品!\n");
	}

	/**
	 * 更新药品信息
	 * @param theProduct
	 */
	public void updateProduct(Product theProduct){
		String name = theProduct.getProductname();
		log("更新" +name+"药品");
		try{
			Path path = Paths.get(PRODUCT_FILE_NAME);
			List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);

			//找到需要修改的用户名所在的行数，并将其替换为新的用户信息
			int lineToUpdate = -1;
			for (int i = 0;i < lines.size(); i++){
				String[] parts = lines.get(i).split(",");
				if (parts[0].equals(name)) {
					lineToUpdate = i;
					String productInfo = theProduct.getProductname()+","+theProduct.getCas()+","+theProduct.getStructure()+","+ theProduct.getFormula()+","+ theProduct.getPrice()+","+ theProduct.getRealstock()+","+ theProduct.getCategory();
					lines.set(i, productInfo); //使用新的药品信息替换原有的行
					break;
				}
			}
			// 如果找到了需要修改的用户名，则将其对应的行更新
			if (lineToUpdate != -1) {
				Files.write(path, lines, StandardCharsets.UTF_8);
				log("已成功更新药品：" + name);
			} else {
				log("未找到指定的用户！");
				return;
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	/**
	 * 删除产品信息
	 */
	public void deleteProduct(Product theProduct){
		String productName = theProduct.getProductname();
		log("删除"+productName+" 药品");
		try{
			// 读取药品文件
			Path path = Paths.get(PRODUCT_FILE_NAME);
			List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);

			//找到需要删除商品的位置
			int lineToProduct = -1;
			for(int i =0;i<lines.size();i++){
				String[] parts = lines.get(i).split(",");
				if(parts[0].equals(productName)){
					lineToProduct = i;
					break;
				}
			}
			//找到产品
			if(lineToProduct!=-1){
				lines.remove(lineToProduct);
			}else{
				log("删除失败");
				return;
			}

			//将新的行写回文件中，覆盖原有内容
			Files.write(path,lines,StandardCharsets.UTF_8);
			log("成功删除产品： "+productName);

		}catch (IOException e){
			e.printStackTrace();
		}

	}


	/**
	 * 获得某类产品的集合
	 * @param category 分类名称
	 * @return productList 商品集合
	 */
	@SuppressWarnings("unchecked")
	public ArrayList<Product> getProducts(String category) {
		load();
		log("获得产品集合信息， 它们属于: " + category);
		ArrayList<Product> productList = dataTable.get(category);
		log("该类产品数量：" + productList.size());
		// 排序
		Collections.sort(productList);
		log("完成获得产品集合信息!\n");
		return productList;
	}
	public ArrayList<String> getCategories() {
		load();
		Set<String> categorySet = dataTable.keySet();
		log("获得分类...");
		ArrayList<String> categories = new ArrayList<String>(categorySet);
		// 排序
		Collections.sort(categories);
		log("完成获得分类!\n");
		return categories;
	}

	/**
	 * 返回带有这些参数的商品对象
	 * @param productName 药品名称
	 * @param cas 化学文摘登记号
	 * @param structure 结构图名称
	 * @param formula 公式
	 * @param price 价格
	 * @param realstock 数量
	 * @param category 类别
	 * @return new Product(productName, cas, structure, formula, price, realstock, category);
	 */
	private Product getProductObject(String productName, String cas,
									 String structure, String formula, String price, String realstock, String category) {
		return new Product(productName, cas, structure, formula, price, realstock, category);
	}
}